package com.qyer.search.template;

import static com.qyer.commons.blender.BlenderLayoutPattern.DEFAULT_COUNT_PER_KEY;

import com.qyer.commons.blender.BlenderLayoutPattern;
import com.qyer.search.Constants;
import com.qyer.search.annotation.TemplateName;
import com.qyer.search.enums.SKUType1;
import com.qyer.search.enums.SKUType2;
import com.qyer.search.enums.ZSKUSTG;
import com.qyer.search.model.SearchParameter;
import com.qyer.search.model.SearchParameterOrigin;
import com.qyer.search.model.result.SearchEntity;
import com.qyer.search.model.result.SearchPackage;
import com.qyer.words.model.Word;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServlet;
import java.io.Writer;
import java.util.List;
import java.util.Set;

public class VMTemplate {

  private static final Logger LOGGER = LoggerFactory.getLogger(VMTemplate.class);

  private static class InnerHolder {

    private static final VMTemplate INSTANCE = new VMTemplate();
  }

  private VMTemplate() {
    init();
  }

  public static final VMTemplate getInstance() {
    return InnerHolder.INSTANCE;
  }

  private VelocityEngine ve;

  private void init() {
    this.ve = new VelocityEngine();
    ve.setProperty(Velocity.ENCODING_DEFAULT, "utf8");
    ve.setProperty(Velocity.INPUT_ENCODING, "utf8");
    ve.setProperty(Velocity.OUTPUT_ENCODING, "utf8");
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    this.ve.init();
  }

  public void mergeSearchResult(SearchParameterOrigin searchParameter, Set<List<Word>> candidateWords,
                                List<? extends SearchPackage> packages, long requestTime,
                                HttpServlet servlet, Writer writer, boolean useSimpleResult,
                                boolean blendResult,
                                List<BlenderLayoutPattern<Integer>> blendLayouts) {
    TemplateName tn = servlet.getClass().getAnnotation(TemplateName.class);
    Template template = ve.getTemplate(tn.value());
    VelocityContext ctx = new VelocityContext();
    ctx.put("param", searchParameter);
    ctx.put("candidateWords", candidateWords);
    ctx.put("result", packages);
    ctx.put("requestTime", requestTime);
    ctx.put("useSimpleResult", useSimpleResult);
    ctx.put("blendResult", blendResult);
    ctx.put("blendLayouts", blendLayouts);
    ctx.put("maxRandomNum", DEFAULT_COUNT_PER_KEY);
    ctx.put("skuType1Map", SKUType1.SKU_TYPE1_MAP);
    ctx.put("skuType2Map", SKUType2.SKU_TYPE2_MAP);
    ctx.put("sourcePlaceMap", Constants.START_POS_MAP_INVERS);
    ctx.put("projectName", Constants.PROJECT_NAME);
    ctx.put("projectNamespace", Constants.PROJECT_NAMESPACE);
    template.merge(ctx, writer);
  }

  public void mergeSearchResult(SearchParameterOrigin searchParameter, Set<List<Word>> candidateWords,
                                List<? extends SearchPackage> packages, long requestTime,
                                HttpServlet servlet, Writer writer, boolean useSimpleResult,
                                boolean blendResult,
                                List<BlenderLayoutPattern<Integer>> blendLayouts, String startTime, String limit) {
    TemplateName tn = servlet.getClass().getAnnotation(TemplateName.class);
    Template template = ve.getTemplate(tn.value());
    VelocityContext ctx = new VelocityContext();
    ctx.put("param", searchParameter);
    ctx.put("candidateWords", candidateWords);
    ctx.put("result", packages);
    ctx.put("requestTime", requestTime);
    ctx.put("useSimpleResult", useSimpleResult);
    ctx.put("blendResult", blendResult);
    ctx.put("blendLayouts", blendLayouts);
    ctx.put("maxRandomNum", DEFAULT_COUNT_PER_KEY);
    ctx.put("skuType1Map", SKUType1.SKU_TYPE1_MAP);
    ctx.put("skuType2Map", SKUType2.SKU_TYPE2_MAP);
    ctx.put("sourcePlaceMap", Constants.START_POS_MAP_INVERS);
    ctx.put("projectName", Constants.PROJECT_NAME);
    ctx.put("projectNamespace", Constants.PROJECT_NAMESPACE);
    ctx.put("startTime", startTime);
    ctx.put("limit", limit);
    template.merge(ctx, writer);
  }

  public void mergeSearchResult(SearchParameterOrigin searchParameter, Set<List<Word>> candidateWords,
                                List<? extends SearchEntity> packages, long requestTime,
                                HttpServlet servlet, Writer writer, boolean useSimpleResult,
                                boolean blendResult,
                                List<BlenderLayoutPattern<Integer>> blendLayouts, String startTime) {
    TemplateName tn = servlet.getClass().getAnnotation(TemplateName.class);
    Template template = ve.getTemplate(tn.value());
    VelocityContext ctx = new VelocityContext();
    ctx.put("param", searchParameter);
    ctx.put("candidateWords", candidateWords);
    ctx.put("result", packages);
    ctx.put("requestTime", requestTime);
    ctx.put("useSimpleResult", useSimpleResult);
    ctx.put("blendResult", blendResult);
    ctx.put("blendLayouts", blendLayouts);
    ctx.put("maxRandomNum", DEFAULT_COUNT_PER_KEY);
    ctx.put("skuType1Map", ZSKUSTG.SKU_TYPE1_MAP);
    //ctx.put("skuType2Map", SKUType2.SKU_TYPE2_MAP);
    ctx.put("sourcePlaceMap", Constants.START_POS_MAP_INVERS);
    ctx.put("projectName", Constants.PROJECT_NAME);
    ctx.put("projectNamespace", Constants.PROJECT_NAMESPACE);
    ctx.put("startTime", startTime);
    //ctx.put("limit", limit);
    template.merge(ctx, writer);
  }

  public void mergeSearchResult2(SearchParameterOrigin searchParameter, Set<List<Word>> candidateWords,
                                List<? extends SearchEntity> packages, long requestTime,
                                HttpServlet servlet, Writer writer, boolean useSimpleResult,
                                boolean blendResult,
                                List<BlenderLayoutPattern<Integer>> blendLayouts, String startTime) {
    TemplateName tn = servlet.getClass().getAnnotation(TemplateName.class);
    Template template = ve.getTemplate(tn.value());
    VelocityContext ctx = new VelocityContext();
    ctx.put("param", searchParameter);
    ctx.put("candidateWords", candidateWords);
    ctx.put("result", packages);
    ctx.put("requestTime", requestTime);
    ctx.put("useSimpleResult", useSimpleResult);
    ctx.put("blendResult", blendResult);
    ctx.put("blendLayouts", blendLayouts);
    ctx.put("maxRandomNum", DEFAULT_COUNT_PER_KEY);
    ctx.put("skuType1Map", ZSKUSTG.SKU_TYPE1_MAP);
    //ctx.put("skuType2Map", SKUType2.SKU_TYPE2_MAP);
    ctx.put("sourcePlaceMap", Constants.START_POS_MAP_INVERS);
    ctx.put("projectName", Constants.PROJECT_NAME);
    ctx.put("projectNamespace", Constants.PROJECT_NAMESPACE);
    ctx.put("startTime", startTime);
    //ctx.put("limit", limit);
    template.merge(ctx, writer);
  }

}
